package com.sky.aspect;

import com.sky.anno.AtuoFill;
import com.sky.constant.AutoFillConstant;
import com.sky.context.BaseContext;
import com.sky.enumeration.OperationType;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.time.LocalDateTime;

/**
 * @Description 共自动填充切面，用于在新增和修改操作时自动填充创建时间、创建人、更新时间、更新人等字段
 * @Author shh
 * @Date 2025-10-05
 */
@Aspect//切面类
@Component//组件类
@Slf4j
public class AtuoFillAspect {
    /**
     * @Description 在目标方法执行前，自动填充创建时间、创建人、更新时间、更新人等字段
     * @Author shh
     * @Date 2025-10-05
     */
    @Before("@annotation(com.sky.anno.AtuoFill)")//详细说明：在目标方法执行前，自动填充创建时间、创建人、更新时间、更新人等字段
    public void autoFill(JoinPoint joinPoint) {
        log.info("自动填充切面开始执行...");
        //1.获取目标方法上的注解，并拿到注解上的属性值。
        MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();//获取方法签名,方法签名：包含方法参数信息
        Method method = methodSignature.getMethod();//获取方法对象,包含方法参数信息
        AtuoFill atuoFill = method.getAnnotation(AtuoFill.class);//获取方法上的注解对象
        OperationType operationType = atuoFill.value();//获取注解上的属性值
        //2.获取目标方法的参数对象
        Object[] args = joinPoint.getArgs();//获取目标方法的参数对象数组

        if (args==null || args.length==0) {//如果参数数组为空或长度为0,则直接返回,不进行自动填充
            log.info("自动填充切面结束执行...");
            return;
        }
        Object entity = args[0];//获取目标方法的第一个参数对象,假设是实体对象
        //3.根据注解上的属性值，判断是新增操作还是修改操作。

        try {
            if (operationType == OperationType.INSERT) {
                //通过字节码去补充属性值
                // 新增操作：自动填充创建时间、创建人、更新时间、更新人等字段
                Method createTimeMethod = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_CREATE_TIME, LocalDateTime.class);//获取实体类的setCreateTime方法
                createTimeMethod.invoke(entity, LocalDateTime.now());//调用setCreateTime方法，设置创建时间为当前时间
                Method createUserMethod = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_CREATE_USER, Long.class);//获取实体类的setCreateUser方法
                createUserMethod.invoke(entity, BaseContext.getCurrentId());//调用setCreateUser方法，设置创建人id为当前登录用户id
                Method updateTimeMethod = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_TIME, LocalDateTime.class);//获取实体类的setUpdateTime方法
                updateTimeMethod.invoke(entity, LocalDateTime.now());//调用setUpdateTime方法，设置更新时间为当前时间
                Method updateUserMethod = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_USER, Long.class);//获取实体类的setUpdateUser方法
                updateUserMethod.invoke(entity, BaseContext.getCurrentId());//调用setUpdateUser方法，设置更新人id为当前登录用户id
            } else if (operationType == OperationType.UPDATE) {
                // 修改操作：自动填充更新时间、更新人等字段
                Method updateTimeMethod = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_TIME, LocalDateTime.class);//获取实体类的setUpdateTime方法
                updateTimeMethod.invoke(entity, LocalDateTime.now());//调用setUpdateTime方法，设置更新时间为当前时间
                Method updateUserMethod = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_USER, Long.class);//获取实体类的setUpdateUser方法
                updateUserMethod.invoke(entity, BaseContext.getCurrentId());//调用setUpdateUser方法，设置更新人id为当前登录用户id
            }
        } catch (Exception e) {
            throw new RuntimeException("自动填充字段失败", e);//抛出运行时异常，包含异常信息
        }
    }
}
